/**
 * TextureData.cpp
 *
 * Author:
 *   Chris Herbison
 *
 * Description:
 *   Class that holds color data for all objects.
 */

#include "TextureData.h"

/*
 * Constructor for a solid color.
 *
 * _ca - The ambient color of this object.
 * _cd- The diffuse color of this object.
 * _cs - The specular color of this object.
 */
TextureData::TextureData(MyColor _ca, MyColor _cd, MyColor _cs):
                         ca(_ca), cd(_cd), cs(_cs){
}

/*
 * Constructor for a 1-D texture.
 *
 * _ca - The ambient texture of this object.
 * _cd - The diffuse texture of this object.
 * _cs - The specular texture of this object.
 * _stretch - Whether the textures should be stretched over the object or repeated over the object.
 * _over - Which coordinate to interpolate over for the texture {x,y,z} = {0,1,2}.
 * _offset - The [_over] offset from origin of the object's lower left coordinate.
 * _ratio - The ratio of object's [_over] length to texture's length.
 */
TextureData::TextureData(vector<MyColor> _ca, vector<MyColor> _cd, vector<MyColor> _cs, bool _stretch, int _over, double _offset, double _ratio):
                         ca1d(_ca), cd1d(_cd), cs1d(_cs), stretch(_stretch), over(_over), hOffset(_offset), hRatio(_ratio){
}

/*
 * Constructor for a 2-D texture.
 *
 * _ca - The ambient texture of this object.
 * _cd - The diffuse texture of this object.
 * _cs - The specular texture of this object.
 * _stretch - Whether the textures should be stretched over the object or repeated over the object.
 * _over - Which coordinates to interpolate over for the texture {xy,xz,yz} = {0,1,2}. (Note: if over is xy (or 0), then _over[0] = x, and _over[1] = y)
 * _hOffset - The horizontal (over[0]) offset from origin of the object's lower left coordinate.
 * _vOffset - The vertical (over[1]) offset from origin of the object's lower left coordinate.
 * _hRatio - The horizontal (over[0]) ratio of object to texture.
 * _vRatio - The vertical (over[1]) ratio of object to texture.
 */
TextureData::TextureData(vector<vector<MyColor> > _ca, vector<vector<MyColor> > _cd, vector<vector<MyColor> > _cs, bool _stretch, int _over, double _hOffset, double _vOffset, double _hRatio, double _vRatio):
                         ca2d(_ca), cd2d(_cd), cs2d(_cs), stretch(_stretch), over(_over), hOffset(_hOffset), vOffset(_vOffset), hRatio(_hRatio), vRatio(_vRatio){
}
 
/*
 * Constructor for a 3-D texture.
 *
 * _ca - The ambient texture of this object.
 * _cd - The diffuse texture of this object.
 * _cs - The specular texture of this object.
 * _stretch - Whether the textures should be stretched over the object or repeated over the object.
 * _hOffset - The horizontal (x) offset from origin of the object's lower left coordinate.
 * _vOffset - The vertical (y) offset from origin of the object's lower left coordinate.
 * _dOffset - The vertical (z) offset from origin of the object's lower left coordinate.
 * _hRatio - The horizontal (x) ratio of object to texture.
 * _vRatio - The vertical (y) ratio of object to texture.
 * _dRatio - The vertical (z) ratio of object to texture.
 */
TextureData::TextureData(vector<vector<vector<MyColor> > > _ca, vector<vector<vector<MyColor> > > _cd, vector<vector<vector<MyColor> > > _cs, bool _stretch, double _hOffset, double _vOffset, double _dOffset, double _hRatio, double _vRatio, double _dRatio):
                         ca3d(_ca), cd3d(_cd), cs3d(_cs), stretch(_stretch), hOffset(_hOffset), vOffset(_vOffset), dOffset(_dOffset), hRatio(_hRatio), vRatio(_vRatio), dRatio(_dRatio){
}

/*
 * Gets the color of the object at a given point on the object.
 *
 * p - The point on the object to get the color from.
 *
 * returns - The colors {ambient, diffuse, specular} of the object at point p.
 */
vector<MyColor> TextureData::getColors(Point3 p){
     vector<MyColor> retColors;
     
     //Handle 1-D Texture
     if(ca1d.size() > 0){
          double s;
          if(over == 0){
               s = p.x;
          }
          else if(over == 1){
               s = p.y;
          }
          else{
               s = p.z;
          }
          if(stretch){
               retColors.push_back(ca1d.at((int)((s-hOffset)/hRatio)));
               retColors.push_back(cd1d.at((int)((s-hOffset)/hRatio)));
               retColors.push_back(cs1d.at((int)(s-hOffset) % cs2d.size()));
          }
          else{
               retColors.push_back(ca1d.at((int)(s-hOffset) % ca1d.size()));
               retColors.push_back(cd1d.at((int)(s-hOffset) % cd1d.size()));
               retColors.push_back(cs1d.at((int)(s-hOffset) % cs1d.size()));
          }
     }
     
     //Handle 2-D Texture
     else if(ca2d.size() > 0){
          double s, t;
          if(over == 0){
               s = p.x;
               t = p.y;
          }
          else if(over == 1){
               s = p.x;
               t = p.z;
          }
          else{
               s = p.y;
               t = p.z;
          }
          if(stretch){
               retColors.push_back(ca2d.at((int)((s-hOffset)/hRatio)).at((int)((t-vOffset)/vRatio)));
               retColors.push_back(cd2d.at((int)((s-hOffset)/hRatio)).at((int)((t-vOffset)/vRatio)));
               retColors.push_back(cs2d.at((int)(s-hOffset) % cs2d.size()).at((int)(t-vOffset) % cs2d.at(0).size()));
          }
          else{
               retColors.push_back(ca2d.at((int)(s-hOffset) % ca2d.size()).at((int)(t-vOffset) % ca2d.at(0).size()));
               retColors.push_back(cd2d.at((int)(s-hOffset) % cd2d.size()).at((int)(t-vOffset) % cd2d.at(0).size()));
               retColors.push_back(cs2d.at((int)(s-hOffset) % cs2d.size()).at((int)(t-vOffset) % cs2d.at(0).size()));
          }
     }

     //Handle 3-D Texture
     else if(ca3d.size() > 0){
          double s = p.x;
          double t = p.y;
          double u = p.z;
          if(stretch){
               retColors.push_back(ca3d.at((int)((s-hOffset)/hRatio)).at((int)((t-vOffset)/vRatio)).at((int)((u-dOffset)/dRatio)));
               retColors.push_back(cd3d.at((int)((s-hOffset)/hRatio)).at((int)((t-vOffset)/vRatio)).at((int)((u-dOffset)/dRatio)));
               retColors.push_back(cs3d.at((int)(s-hOffset) % cs3d.size()).at((int)(t-vOffset) % cs3d.at(0).size()).at((int)(u-dOffset) % cs3d.at(0).at(0).size()));
          }
          else{
               retColors.push_back(ca3d.at((int)(s-hOffset) % ca3d.size()).at((int)(t-vOffset) % ca3d.at(0).size()).at((int)(u-dOffset) % cs3d.at(0).at(0).size()));
               retColors.push_back(cd3d.at((int)(s-hOffset) % cd3d.size()).at((int)(t-vOffset) % cd3d.at(0).size()).at((int)(u-dOffset) % cs3d.at(0).at(0).size()));
               retColors.push_back(cs3d.at((int)(s-hOffset) % cs3d.size()).at((int)(t-vOffset) % cs3d.at(0).size()).at((int)(u-dOffset) % cs3d.at(0).at(0).size()));
          }
     }

     //Handle Non-Textured
     else{
          retColors.push_back(ca);
          retColors.push_back(cd);
          retColors.push_back(cs);
     }

     return retColors;
}
